/*
 * thermal.h
 *
 *  Created on: Mar 12, 2012
 *      Author: qian
 */

#include <stdio.h>
#include "stack.h"
#include "auxiliary.h"

#ifndef THERMAL_H_
#define THERMAL_H_

#define SP_BEOL 	2.1745e6 //(J/m^3-k)
#define SP_SILICON 	1.638e6 //(J/m^3-k)
#define SP_FLUID 	4.172638e6 //(J/m^3-k)
#define Dyn_Vis		0.0007978	/*Pa.s*/
#define Density_Fluid	1000			/*kg/m^3*/

/* grid to block mapping mode	*/
#define	GRID_AVG	0
#define	GRID_MIN	1
#define	GRID_MAX	2
#define	GRID_CENTER	3

/* package layers components*/
// Spreader
#define SP_W		0
#define	SP_E		1
#define SP_N 		2
#define SP_S		3
// Heat Sink
#define SINK_C_W	4
#define SINK_C_E	5
#define SINK_C_N	6
#define	SINK_C_S	7
#define SINK_W		8
#define	SINK_E		9
#define SINK_N		10
#define SINK_S		11

#define AMBIENT 300 //Kelvin

#define BIDIRECT 0 //bidirectional flow flag


/* package parameters	*/
typedef struct package_thermal_st
{
	/*core part thermal resistances of spreader and sink*/
	double sp_rx;
	double sp_ry;
	double sp_rz;
	double sink_rx;
	double sink_ry;
	double sink_rz;
	double sink_ramb;

	/* lateral R's of spreader and sink, all are from centre of the node to its corresponding edge*/
	/* lateral resistances of west and east extra nodes of spreader (to core)*/
	double rx_sp_per;
	/* lateral resistances of north and south extra nodes of spreader (to core)*/
	double ry_sp_per;
	/* lateral resistances of west and east middle extra nodes of heatsink (to core)*/
	double rx_hs_ci;
	/* lateral resistances of north and south middle extra nodes of heatsink (to core)*/
	double ry_hs_ci;
	/* lateral resistances of west and east middle extra nodes of heatsink (to outer extra nodes of heatsink)*/
	double rx_hs_co;
	/* lateral resistances of north and south middle extra nodes of heatsink (to outer extra nodes of heatsink)*/
	double ry_hs_co;
	/* lateral resistances of outer extra nodes of heatsink (to middle extra nodes of heatsink,
	 * four of them are identical since both spreader and heatsink are squarish)*/
	double rxy_hs_outer;

	/* vertical R's of spreader and sink, from centre to edge */
	/* peripheral spreader nodes */
	double rz_sp_we;
	double rz_sp_ns;
	/* sink's inner periphery	*/
	double rz_hs_c_we;
	double rz_hs_c_ns;
	/* sink's outer periphery	*/
	double rz_hs_outer;

	/* vertical R's from heatsink to ambient (divide r_convec proportional to area) */
	/* sink's inner periphery	*/
	double ramb_c_we;
	double ramb_c_ns;
	/* sink's outer periphery	*/
	double ramb_outer;

	/*thermal conductances of thermal interface material*/
	double 	tim_gx;
	double 	tim_gy;
	double 	tim_gz;
}package_thermal_t;

/*Microchannel related thermal conductances*/
typedef struct channel_thermal_st
{
	double 	*h_ch;
	double 	*flowrate;
	double 	*Tch;
	double	*ch_gx;
	double 	*ch_gz;
	double 	wall_gx;
	double 	wall_gy;
	double	wall_gz;
}channel_thermal_t;

typedef struct thermal_data_st
{
	/*circuit cells' power consumption values, act as the heat source*/
	double 	*power_grid;
	/*circuit layer cell's thermal conductances, assumed to be identical throughout a layer.*/
	double 	*gx_BEOL;
	double 	*gy_BEOL;
	double 	*gz_BEOL;
	double 	*gx_source;
	double	*gy_source;
	double	*gz_source;
	double	*gx_bulk;
	double	*gy_bulk;
	double	*gz_bulk;

	/*Cooling package*/
	union
	{
		package_thermal_t *pk_thermal;
		channel_thermal_t *ch_thermal;
	};

	double 	*steady_temp_grid;
	double 	*steady_temp_block;
	int map_mode;
} thermal_data_t;


/*allocate memory for thermal data*/
thermal_data_t *init_thermal_data(stk_descr_t* stk);

/*populate thermal data, fill in power information and produce conductances*/
void fill_thermal_data(stk_descr_t *stk, thermal_data_t *thermo);

/*compute steady state temperature*/
void solve_steady_state(stk_descr_t *stk, thermal_data_t *thermo);

/*store unit powers into a 1-D array*/
double *obtain_unit_powers(stk_descr_t *stk);

/*fill in conductances regarding die cells*/
void populate_silicon_conductances(stk_descr_t *stk, thermal_data_t *thermo);

/*fill in channel and wall conductances*/
void populate_channel_conductances(stk_descr_t *stk, thermal_data_t *thermo);

void populate_package_conductances(stk_descr_t *stk, thermal_data_t *thermo);

void solve_steady_state_heatsink(stk_descr_t *stk, thermal_data_t *thermo);

void solve_steady_state_ch(stk_descr_t *stk, thermal_data_t *thermo);

/*calculate thermal transfer coefficient of each channel subject to their respective flowrate*/
void populate_h_ch(stk_descr_t *stk, thermal_data_t *thermo);

/*map block power/temperature to grid*/
void xlate_vector_b2g(stk_descr_t *stk, thermal_data_t *thermo, double *b, int type);

/* translate temperature between grid and block vectors	*/
void xlate_temp_g2b(stk_descr_t *stk, thermal_data_t *thermo);

/*pad in the default flowrate*/
void fill_default_flowrate(stk_descr_t *stk, thermal_data_t *thermo);

/*debug use, print out conductances*/
void check_conductances(stk_descr_t* stk, thermal_data_t *thermo);

/*debug use, print out the whole klu matrix in dense form*/
void print_klu_matrix(int *Ap, int *Ai, double *Ax, double *p, int size);

/*output simulation results*/
void dump_outputs(IO_t *IO, stk_descr_t *stk, thermal_data_t *thermo);

/*clean data structures after simulation*/
void clean_thermal_data(stk_descr_t *stk, thermal_data_t *thermo);
void clean_pk_thermal(package_thermal_t *pk_thermal);
void clean_ch_thermal(channel_thermal_t *ch_thermal);
void clean_stk_description(stk_descr_t *stk);
void clean_layers(stk_descr_t *stk);


#endif /* THERMAL_H_ */
